#include "lpt.hpp"
#include "lpt_error.hpp"
#include "lpt_wget.hpp"
#include "lpt_pkobj.hpp"
#include "lpt_myapp.hpp"
string version_tostring(int v);
myapp::myapp(){
    cout<<"正在读取软件包信息...\n";
    ifstream fin;
    string tmp;
    #ifdef DEBUG
    fin.open("./docker/installed.list");
    #else
    fin.open("/etc/lpt/installed.list");
    #endif
    if(fin.is_open()==0) lpt_error("不能正确地读取已安装的软件包有关信息，请提升权限或检查包管理器配置文件完整性");
    while (!fin.eof()){
        getline(fin,tmp);
        if(tmp!="") name_list.push_back(tmp);
    }
    fin.close();
    getplat();
    getsources_list();
    //for(int i=0;i<name_list.size();i++) version_list.push_back(getversion_list(name_list[i]));
    //for(int i=0;i<name_list.size();i++) version_last.push_back(getversion_last(name_list[i]));
}
myapp::~myapp(){
    string file;
    ofstream fout;
    file="/etc/lpt/installed.list";
    #ifdef DEBUG
    file = "./docker/installed.list";
    #endif
    fout.open(file,ios::out);
    if(!fout.is_open()) lpt_error("无法写入软件列表");
    for(int i=0;i<name_list.size();i++) fout<<name_list[i]<<endl;
    fout.close();
}
int myapp::getversion_list(string pk){
    ifstream fin;
    string file;
    #ifdef DEBUG
    file="./docker/installed/"+pk+"/info";
    #else
    file="/etc/lpt/installed/"+pk+"/info";
    #endif
    fin.open(file);
    if(!fin.is_open()){
        cout<<"警告：您的配置文件中显示您安装了软件包\""+pk+"\"，\n";
        cout<<"但此软件包并不存在于您的计算机中\n";
        return 0;
    }
    fin.close();
    pkobject p1(file);
    return p1.version;
}
int myapp::getversion_last(string pk){
    string url,loc;
    loc = "/etc/lpt/pktmp";
    #ifdef DEBUG
    loc = "./docker/pktmp";
    #endif
    for(int j=0;j<sources_list.size();j++){
        url = sources_list[j]+pk+"/info";
        #ifdef DEBUG
        url = "./docker/server/"+pk+"/info";
        #endif
        if(lpt_wget_getandcheck(url,loc)){
            pkobject p1(loc);
            return p1.version;
        }
    }
    cout<<"注意： 您安装的软件包\""+pk+"\"并不存在于当前的软件源中，它可能已经被移除或重命名\n";
    return 0;
}
void myapp::getsources_list(){
    ifstream fin;
    string tmp,file;
    #ifdef DEBUG
    file="./docker/sources.list";
    #else
    file="/etc/lpt/sources.list";
    #endif
    fin.open(file);
    if(fin.is_open()==0) lpt_error("不能正确地读取软件源相关信息，请提升权限或检查包管理器配置文件完整性");
    while(!fin.eof()){
        getline(fin,tmp);
        if(tmp!="") sources_list.push_back(tmp);
    }
    fin.close();
}
void myapp::install(string pk){
    bool ptr=0;
    string infofile,objfile,objdir;
    string platstr;
    string tmp;
    int v;
    objfile = "/etc/lpt/pktmp.tar";
    objdir = "/etc/lpt/installed";
    infofile = "/etc/lpt/pktmp";
    #ifdef DEBUG
    objfile = "./docker/pktmp.tar";
    objdir =   "./docker/installed";
    infofile = "./docker/pktmp";
    #endif
    for(int i=0;i<name_list.size();i++){
        if(name_list[i]==pk){
            update(pk,0);
            return;
        }
    }
    cout<<"正在查找软件包 \""+pk+"\" 相关的信息\n";
    if(!install_download_info(pk)) lpt_error("软件源中找不到要安装的软件包 \""+pk+"\"\n");
    pkobject p1(infofile);
    for(int i=0;i<plat.size();i++){
        for(int j=0;j<p1.pkplat.size();j++){
            if(plat[i]==p1.pkplat[j]){
                platstr=plat[i];
                ptr=1;break;
            }
        }
        if(ptr==1) break;
    }
    if(!ptr) lpt_error("软件包 \""+pk+"\" 没有适合您的计算机的版本");
    ptr=0;
    cout<<"软件包:\t"+pk+"\n";
    cout<<"版本:\t"<<version_tostring(p1.version)<<endl;
    cout<<"平台:\t"+platstr<<endl;
    cout<<"您确定要安装这个包吗? y-是/n-否>";cin>>tmp;
    if(tmp!="y"&&tmp!="Y"&&tmp!="是") lpt_error("用户已终止安装");
    cout<<"正在下载软件包......\n";
    if(!install_download_tar(pk,platstr)) lpt_error("软件包 \""+pk+"\" 的信息中显示具有适合您计算机的版本\n但它的相关文件并不存在于软件源中");
    cout<<"正在解压......\n";
    if(system(((string)("tar -xf "+objfile+" -C "+objdir)).c_str())) lpt_error("解压失败");
    cout<<"开始安装...\n";
    if(system(((string)("chmod 777 -R "+objdir+"/"+pk)).c_str())) lpt_error("无法赋予执行权限");
    if(system(((string)(objdir+"/"+pk+"/install")).c_str())) lpt_error("安装出错");
    cout<<"安装结束\n";
    //version_last.push_back(p1.version);
    //version_list.push_back(p1.version);
    name_list.push_back(p1.pkname);
    return;

}
void myapp::update(string pk,int check){
    bool ptr=0;
    string infofile,objfile,objdir;
    string platstr;
    string tmp;
    int v;
    objfile = "/etc/lpt/pktmp.tar";
    objdir = "/etc/lpt/installed";
    infofile = "/etc/lpt/pktmp";
    #ifdef DEBUG
    objfile = "./docker/pktmp.tar";
    objdir =   "./docker/installed";
    infofile = "./docker/pktmp";
    #endif
    cout<<"正在查找软件包 \""+pk+"\" 相关的信息\n";
    if(!install_download_info(pk)) lpt_error("软件源中找不到要升级的软件包 \""+pk+"\"\n");
    pkobject p1(infofile);
    pkobject pold(objdir+"/"+pk+"/info");
    if(pold.version>=p1.version){ lpt_error("软件包 \""+pk+"\" 已经是最新的版本");return;}
    for(int i=0;i<plat.size();i++){
        for(int j=0;j<p1.pkplat.size();j++){
            if(plat[i]==p1.pkplat[j]){
                platstr=plat[i];
                ptr=1;break;
            }
        }
        if(ptr==1) break;
    }
    if(!ptr) {lpt_error("软件包 \""+pk+"\" 没有适合您的计算机的可升级版本");return;}
    ptr=0;
    cout<<"软件包:\t"+pk+"\n";
    cout<<"版本:\t"<<version_tostring(p1.version)<<endl;
    cout<<"平台:\t"<<platstr<<endl;
    if(check==0){
        cout<<"您确定要升级这个包吗? y-是/n-否>";cin>>tmp;
        if(tmp!="y"&&tmp!="Y"&&tmp!="是") lpt_error("用户已终止安装");
    }
    cout<<"正在下载软件包......\n";
    if(!install_download_tar(pk,platstr)){lpt_error("软件包 \""+pk+"\" 的信息中显示具有适合您计算机的版本\n但它的相关文件并不存在于软件源中");return;}
    cout<<"正在解压......\n";
    if(system(((string)("tar -xf "+objfile+" -C "+objdir)).c_str())) {lpt_error("解压失败");return;}
    cout<<"开始升级...\n";
    if(system(((string)("chmod 777 -R "+objdir+"/"+pk)).c_str())) {lpt_error("无法赋予执行权限");return;}
    if(system(((string)(objdir+"/"+pk+"/install")).c_str())) {lpt_error("安装出错");return;}
    cout<<"升级结束\n";
    return;
}
void myapp::updateall(){
    string tmp;
    checkupdate();
    if(updateable.size()==0){
        cout<<"所有软件包已经是最新版本\n";
        return;
    };
    showupdate();
    cout<<"您确定要升级这些包吗? y-是/n-否>";cin>>tmp;
    if(tmp!="y"&&tmp!="Y"&&tmp!="是") lpt_error("用户已终止安装");
    closeerr();
    for(int i=0;i<updateable_list.size();i++){
        update(updateable_list[i],1);
    }
    openerr();
}
int myapp::install_download_tar(string pk,string pt){
    string url,loc;
    loc = "/etc/lpt/pktmp.tar";
    #ifdef DEBUG
    loc = "./docker/pktmp.tar";
    #endif
    for(int i=0;i<sources_list.size();i++){
        for(int j=0;j<plat.size();j++){
            url = sources_list[i]+pk+"/"+pt+".tar";
            #ifdef DEBUG
            url = "./docker/server/"+pk+"/"+pt+".tar";
            #endif
            if(lpt_wget_getandcheck(url,loc)) return 1;
        }
    }
    return 0;
}
int myapp::install_download_info(string pk){
    string url,loc;
    loc = "/etc/lpt/pktmp";
    #ifdef DEBUG
    loc = "./docker/pktmp";
    #endif
    for(int j=0;j<sources_list.size();j++){
        url = sources_list[j]+pk+"/info";
        #ifdef DEBUG
        url = "./docker/server/"+pk+"/info";
        #endif
        if(lpt_wget_getandcheck(url,loc)) return 1;
    }
    return 0;
}
void myapp::showall(){
    version_list.clear();
    for(int i=0;i<name_list.size();i++) version_list.push_back(getversion_list(name_list[i]));
    cout<<"系统中已安装的软件包\n名称\t版本\t\n";
    for(int i=0;i<name_list.size();i++){
        cout<<name_list[i]<<"\t"<<version_tostring(version_list[i])<<endl;
    }
}
void myapp::showupdate(){
    cout<<"系统中可升级的软件包有"<<updateable.size()<<"个\n名称\t现有版本\t最新版本\n";
    for(int i=0;i<updateable.size();i++) cout<<updateable[i]<<endl;
}
void myapp::checkupdate(){
    updateable.clear();
    updateable_list.clear();
    version_list.clear();
    version_last.clear();
    for(int i=0;i<name_list.size();i++) version_list.push_back(getversion_list(name_list[i]));
    for(int i=0;i<name_list.size();i++) version_last.push_back(getversion_last(name_list[i]));
    for(int i=0;i<version_list.size();i++){
        if(version_list[i]<version_last[i]){
            updateable.push_back(name_list[i]+"\t"+version_tostring(version_list[i])+"\t"+version_tostring(version_last[i]));
            updateable_list.push_back(name_list[i]);
        }
    }
}
void myapp::getplat(){
    ifstream fin;
    string file,tmp;
    file="/etc/lpt/conf";
    #ifdef DEBUG
    file = "./docker/conf";
    #endif
    fin.open(file);
    if(!fin.is_open()) lpt_error("无法获取平台相关信息，请检查配置文件");
    while (!fin.eof()){
        fin>>tmp;
        if(tmp!="") plat.push_back(tmp);
    }
    fin.close();
}
void myapp::remove(string pk){
    string file,dir,tmp;
    int i;
    for(i=0;i<name_list.size();i++){
        if(name_list[i]==pk) break;
    }
    if(i==name_list.size()) lpt_error("您的计算机中没有安装软件包 \""+pk+"\"");
    cout<<"找到了以下软件包:\t"+pk+"\n";
    cout<<"您确定要卸载这个包吗? y-是/n-否>";cin>>tmp;
    if(tmp!="y"&&tmp!="Y"&&tmp!="是") lpt_error("用户已取消卸载");
    file="/etc/lpt/installed/"+pk+"/uninstall";
    dir="/etc/lpt/installed/"+pk;
    #ifdef DEBUG
    file="./docker/installed/"+pk+"/uninstall";
    dir="./docker/installed/"+pk;
    #endif
    system(((string)(file)).c_str());
    system(((string)("rm -rf "+dir)).c_str()); 
    name_list.erase(name_list.begin()+ i);
    cout<<"卸载结束\n";
    //version_last.erase(version_last.begin()+i);
    //version_list.erase(version_list.begin()+i);
    
}
string version_tostring(int v){
    string v1,v2,v3;
    v3 = to_string(v%32);
    v=v/32;
    v2 = to_string(v%32);
    v=v/32;
    v1 = to_string(v);
    return v1+"."+v2+"."+v3;
}